package com.itheima.health.service.impl;

import com.itheima.health.dao.MemberDao;
import com.itheima.health.dao.OrderDao;
import com.itheima.health.dao.ReportDao;
import com.itheima.health.dao.SetMealDao;
import com.itheima.health.pojo.Order;
import com.itheima.health.pojo.Setmeal;
import com.itheima.health.service.ReportService;
import com.itheima.health.vo.HotSetmealVo;
import com.itheima.health.vo.MemberReport;
import com.itheima.health.vo.OperationsReportVo;
import com.itheima.health.vo.SetmealReport;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private MemberDao memberDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private SetMealDao setMealDao;
    @Autowired
    private ReportDao reportDao;
    //
    //日期：
    //今日
    LocalDate date = LocalDate.now();

    //本周一
    LocalDate firstDayOfWeek = date.with(DayOfWeek.MONDAY);
    //本周末
    LocalDate endDayOfWeek = date.with(DayOfWeek.SUNDAY);



    //本月一
    LocalDate firstDayOfMonth = date.withDayOfMonth(1);

    //本月末
    LocalDate endDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());

    //格式化今日日期
    String today = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

    public static MemberReport memberReport = new MemberReport();
    @Override
    public MemberReport getMemberReport() {
        //判断静态变量是否有值，如果有返回即可，如果没有再查找
        if(memberReport != null && memberReport.getMemberCount() != null && memberReport.getMemberCount().size() == 12){
            return memberReport;
        }

        LocalDate startday = LocalDate.now().minusYears(1);
        List<LocalDate> monthStartdays = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            monthStartdays.add(LocalDate.now().minusMonths(12 - i).withDayOfMonth(1));
        }

        List<String> months = new ArrayList<>();
        List<Integer> memberCount = new ArrayList<>();
        //查找数据库，填充月份和会员总数
        monthStartdays.forEach(localDate -> {
            months.add(localDate.format(DateTimeFormatter.ofPattern("yyyy.MM")));
            memberCount.add(reportDao.selectmemberCount(localDate, localDate.withDayOfMonth(localDate.lengthOfMonth())));
        });
        memberReport.setMonths(months);
        memberReport.setMemberCount(memberCount);

        return memberReport;
    }

    @Override
    public SetmealReport getSetmealReport() {
        //创建vo对象
        SetmealReport setmealReport = new SetmealReport();
        List<Setmeal> setmeals = reportDao.selectSetmealNames();
        List<String> setMealNames = new ArrayList<>();
        //填充name
        setmeals.forEach(setmeal -> {
            setMealNames.add(setmeal.getName());
        });

        //返回数据要求map类型
        List<Map<String, Object>> setmealCount = new ArrayList<>();
        for (int i = 0; i < setmeals.size(); i++) {
            //某一套餐的总人数
            Integer count = reportDao.selectSetmealCount(setmeals.get(i).getId());
            Map<String, Object> setmeal1 = new HashMap<>();
            setmeal1.put("name", setmeals.get(i).getName() );
            setmeal1.put("value", count);
            setmealCount.add(setmeal1);
        }

        setmealReport.setSetmealNames(setMealNames);
        setmealReport.setSetmealCount(setmealCount);
        return setmealReport;
    }

    @Override
    public void exportBusinessReport(HttpServletResponse response) throws Exception {
        //读取Excel模版文件
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("templates/report.xlsx");
        XSSFWorkbook workbook = new XSSFWorkbook(is);
        //获取Excel里的第一个Sheet页
        XSSFSheet sheet =workbook.getSheetAt(0);

        //给报表设置日期范围 第2行第3列
        sheet.getRow(1).getCell(2).setCellValue(today);

        //设置会员数据统计数据
        //新增会员数（今日）
        Integer newMember = memberDao.selectMemberCount(date,date);
        sheet.getRow(3).getCell(2).setCellValue(newMember);
        //总会员数
        Integer allMember = memberDao.selectMemberCount(null, date);
        sheet.getRow(3).getCell(4).setCellValue(allMember);
        //本周新增会员
        Integer weekMember = memberDao.selectMemberCount(firstDayOfWeek, endDayOfWeek);
        sheet.getRow(4).getCell(2).setCellValue(weekMember);
        //本月新增会员
        Integer monthMember = memberDao.selectMemberCount(firstDayOfMonth, endDayOfMonth);
        sheet.getRow(4).getCell(4).setCellValue(monthMember);

        //设置到诊数据统计
        //今日预约数
        Integer todayOrder = orderDao.selectOrderCount(date,date);
        sheet.getRow(6).getCell(2).setCellValue(todayOrder);
        //今日到诊数
        Integer todayOrderYes = orderDao.selectOrderCountYes(date,date, Order.ORDERSTATUS_YES);
        sheet.getRow(6).getCell(4).setCellValue(todayOrderYes);
        //本周预约数
        Integer weekOrder = orderDao.selectOrderCount(firstDayOfWeek, endDayOfWeek);
        sheet.getRow(7).getCell(2).setCellValue(weekOrder);
        //本周到诊数
        Integer weekOrderYes = orderDao.selectOrderCountYes(firstDayOfWeek, endDayOfWeek, Order.ORDERSTATUS_YES);
        sheet.getRow(7).getCell(4).setCellValue(weekOrderYes);
        //本月预约数
        Integer monthOrder = orderDao.selectOrderCount(firstDayOfMonth, endDayOfMonth);
        sheet.getRow(8).getCell(2).setCellValue(monthOrder);
        //本月到诊数
        Integer monthOrderYes = orderDao.selectOrderCountYes(firstDayOfMonth, endDayOfMonth, Order.ORDERSTATUS_YES);
        sheet.getRow(8).getCell(4).setCellValue(monthOrderYes);

        //设置热门套餐数据（套餐名称、预约数量、占比、备注） 从12行开始插入
        int rowNum = 11;
       
        //循环套餐，插入数据
        List<Setmeal> setmeal = setMealDao.selectBySetmeal();

        for (Integer i = 0; i < setmeal.size(); i++) {
            //将套餐名称、预约数量、占比、备注插入进去
            String setmealName = setmeal.get(i).getName();
            //预约数量
            Integer setmealNum = orderDao.selectSetmealCountByOrder(setmeal.get(i).getId());
            //总预约数量
            Integer setmealAllNum = orderDao.selectOrderCountAll(date);
            //占比
            Double proportion = new BigDecimal((1.0 * setmealNum / setmealAllNum)).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue();
            //备注
            String remarks =  setmeal.get(i).getRemark();

            //从12行开始插入  行自增
            XSSFRow row = sheet.getRow(rowNum);
            row.getCell(1).setCellValue(setmealName);
            row.getCell(2).setCellValue(setmealNum);
            row.getCell(3).setCellValue(proportion);
            row.getCell(4).setCellValue(remarks);
            rowNum++;

        }
        response.setHeader("Content-Disposition", "attachment;filename=businessReport.xlsx");
        workbook.write(response.getOutputStream());
        response.getOutputStream().flush();
        response.getOutputStream().close();
        is.close();
        workbook.close();
    }
    /**
     * 15_统计分析-运营统计
     *
     * @return
     */
    @Override
    public OperationsReportVo getBusinessReportData() {
        //会员：

        //今日新增
        Integer todayNewMember = memberDao.selectMemberCount(date, date);
        //总数
        Integer totalMember = memberDao.selectMemberCount(null, date);

        //本周新增
        Integer thisWeekNewMember = memberDao.selectMemberCount(firstDayOfWeek, endDayOfWeek);

        //本月新增
        Integer thisMonthNewMember = memberDao.selectMemberCount(firstDayOfMonth, endDayOfMonth);

        //预约到诊：

        //今日预约
        Integer todayOrderNumber = orderDao.selectOrderCount(date, date);

        //今日到诊
        Integer todayVisitsNumber = orderDao.selectOrderCountYes(date, date, Order.ORDERSTATUS_YES);

        //本周新增预约
        Integer thisWeekOrderNumber = orderDao.selectOrderCount(firstDayOfWeek, endDayOfWeek);

        //本周新增到诊
        Integer thisWeekVisitsNumber = orderDao.selectOrderCountYes(firstDayOfWeek, endDayOfWeek, Order.ORDERSTATUS_YES);

        //本月新增预约
        Integer thisMonthOrderNumber = orderDao.selectOrderCount(firstDayOfMonth, endDayOfMonth);

        //本月新增到诊
        Integer thisMonthVisitsNumber = orderDao.selectOrderCountYes(firstDayOfMonth, endDayOfMonth, Order.ORDERSTATUS_YES);

        //热门套餐：
        //查找热门套餐：
        OperationsReportVo operationsReportVo = new OperationsReportVo();
        List<HotSetmealVo> hotSetmealVoList = orderDao.findHotSetmeal();

        //总订单数
        int allAount = orderDao.selectAllCount();
        //占比Proportion
        for (HotSetmealVo hotSetmealVo : hotSetmealVoList) {

            int count = orderDao.selectCountByName(hotSetmealVo.getName());
            hotSetmealVo.setProportion(new BigDecimal(1.0 * count / allAount).setScale(4, BigDecimal.ROUND_HALF_UP));
        }

        operationsReportVo.setReportDate(today);
        operationsReportVo.setTodayNewMember(todayNewMember);
        operationsReportVo.setTotalMember(totalMember);
        operationsReportVo.setThisWeekNewMember(thisWeekNewMember);
        operationsReportVo.setThisMonthNewMember(thisMonthNewMember);
        operationsReportVo.setTodayOrderNumber(todayOrderNumber);
        operationsReportVo.setThisWeekOrderNumber(thisWeekOrderNumber);
        operationsReportVo.setThisMonthOrderNumber(thisMonthOrderNumber);
        operationsReportVo.setTodayVisitsNumber(todayVisitsNumber);
        operationsReportVo.setThisWeekVisitsNumber(thisWeekVisitsNumber);
        operationsReportVo.setThisMonthVisitsNumber(thisMonthVisitsNumber);
        operationsReportVo.setHotSetmeal(hotSetmealVoList);

        return operationsReportVo;
    }
}
